#pragma once

#include <string>
#include <utility>
#include <sstream>
#include <tuple>
#include "utility.hpp"


namespace cpp{

	namespace __string{

		template<class Ch, class Tr, class Alloc, class... Args, size_t ... I>
		inline std::basic_string<Ch, Tr, Alloc> to_basic_string_impl(std::tuple< Args...> && tp, index_sequence<I...>)
		{
			std::basic_ostringstream<Ch, Tr, Alloc> stream;
			stream.exceptions(std::ios_base::failbit | std::ios_base::badbit);
			using __ = int[];
			(void)__{0, (stream << std::get <I>(std::move(tp)), 0)... };
			return stream.str();
		}
	}

	template<class Ch, class Tr = std::char_traits<Ch>, class Alloc = std::allocator<Ch>, class... Args>
	std::basic_string<Ch, Tr, Alloc> to_basic_string(Args&&... args)
	{
	#if 1
		std::basic_ostringstream<Ch, Tr, Alloc> stream;
		stream.exceptions(std::ios_base::failbit | std::ios_base::badbit);
		(stream << ... << std::forward<Args>(args));
		return stream.str();
	#else

		return __string::to_basic_string_impl<Ch, Tr, Alloc>(std::forward_as_tuple(std::forward<Args>(args)...), make_index_sequence<sizeof...(Args)>());

	#endif
	}

	template<class... Args>
	inline std::string to_string(Args&&... args)
	{
		return to_basic_string<char>(std::forward<Args>(args)...);
	}

	template<class... Args>
	inline std::wstring to_wstring(Args&&... args)
	{
		return to_basic_string<wchar_t>(std::forward<Args>(args)...);
	}


}

